#!/usr/bin/perl
use Term::ANSIColor;
use File::Spec;
use Getopt::Long;
use Cwd;

my $simulator   = "vcs"; #Support [vlogan, vcs] [nvlog, nelab, nsim] [vlog, vlib, vsim]
my $seed        = "random";
my $cwd         = File::Spec->rel2abs(getcwd());
my $cmp_dir    = "$cwd/cmp_dir";
my $sim_dir     = "$cwd/sim_dir";
my $lsf_enable  = 0;
my $comp_enable = 0;
my $elab_enable = 0;
my $sim_enable  = 0;
my $vhdl_flag   = 0;
my $comp_opt    = "";
my $elab_opt    = "";
my $sim_opt     = "";
my $os32bit     = 0;
my $lsf_opt;
my $comp_log_file = "";
my $elab_log_file = "";
my $sim_log_file = "";
my $comp_log_opt = "";
my $elab_log_opt = "";
my $sim_log_opt = "";
my $quite_flag  = 0;
my $upf_file    = "";
my $lsf_pre_script = "";
my $lsf_post_script = "";
my $job_name        = "";

sub usage() {
    print STDERR << "EOF";
This program is used to resolve dependency at any hierarchy of the IP where 
there is a block_dependency.cfg file.

usage: $0 [-h] {-c | -p | -s | -job_name <job_name> | --git <command>} [-m <level>] 

    -h                      : this (help) message
    -c                      : clone all dependent projects. If project exists, do nothing.
    -p                      : pull all existing projects
    -s                      : check status for all existing projects
    -job_name <job_name>    : Bsub Job Name

    --git <command>         : run the given Git command <command> on all sub-modules
    --gen_filelist <dir>    : generate a complete filelist and env set script onto given output directory <dir>
    --skip <dir_name>       : provides a list of directory (should be git root directory) to skip for the given operation.

    --list                  : only list all paths
    --upf  <FILE_NAME>      : Indicate upf file
    -q                      : quite mode

    -m  <level>             : maximum levels to checkout code, default is the 'max_code_level' value in 'block_config.cfg' file.
                            : if config file does not give such value, then default is 1
                            : setting 0 means unlimited.

EOF
    exit;
}


GetOptions(
  'simulator=s' => \$simulator,
  'seed=s'      => \$seed,
  'cmp_dir=s'  => \$cmp_dir,
  'vhdl!'       => \$vhdl_flag,
  'sim_dir=s'   => \$sim_dir,
  'comp!'       => \$comp_enable,
  'elab!'       => \$elab_enable,
  'sim!'        => \$sim_enable,
  'comp_opt=s'  => \$comp_opt,
  'elab_opt=s'  => \$elab_opt,
  'sim_opt=s'   => \$sim_opt,
  'upf=s'       => \$upf_file,
  'q!'          => \$quite_flag,
  'lsf!'        => \$lsf_enable,
  '32!'         => \$os32bit,
  '-h!'         => \$opt_help,
  'help!'       => \$opt_help,
  'comp_log=s'  => \$comp_log_file,
  'elab_log=s'  => \$elab_log_file,
  'sim_log=s'   => \$sim_log_file,
  'lsf_pre=s'   => \$lsf_pre_script,
  'lsf_post=s'  => \$lsf_post_script,
  'job_name=s'  => \$job_name,
);

usage() if $opt_help;

if($simulator =~ /vcs/i) {
  if($vhdl_flag) {
    if($os32bit) {
      $comp_cmd = "vhdlan";
    } else {
      $comp_cmd = "vhdlan -full64";
    }
  } else {
    if($os32bit) {
      $comp_cmd = "vlogan";
    } else {
      $comp_cmd = "vlogan -full64";
    }
  }
  if($os32bit) {
    $elab_cmd = "vcs";
  } else {
    $elab_cmd = "vcs -full64";
  }
  $sim_cmd  = "$cmp_dir/simv";
  if($comp_log_file ne "") {
    $comp_log_opt = "-l $comp_log_file";
  }
  if($elab_log_file ne "") {
    $elab_log_opt = "-l $elab_log_file";
    if($upf_file ne "") {
      $elab_cmd .= " -upf $upf_file";
    }
  }
  if($sim_log_file ne "") {
    $sim_log_opt = "-l $sim_log_file";
  }
}

if($lsf_enable) {
  $lsf_opt = "bsub";
  if($job_name ne "") {
    $lsf_opt = $lsf_opt." -J $job_name \"";
  } else {
    $lsf_opt = $lsf_opt." \"";
  }
  if($lsf_pre_script ne "") {
    $lsf_opt = $lsf_opt." $lsf_pre_script;";
  }
}

$sim_opt = $sim_opt." +ntb_random_seed=".$seed;
if($quite_flag) {
  $sim_opt = $sim_opt." +vcs+nostdout ";
  $comp_opt = $comp_opt." -q ";
  $elab_opt = $elab_opt." -q ";
}
#$elab_opt = $elab_opt." -ucli +vpi -fsdb";
$elab_opt = $elab_opt." -debug_pp -fsdb";
#$elab_opt = $elab_opt." -debug_pp ";
if($opt_gate) {
  $elab_opt = $elab_opt." +pluse_r/0 +pulse_e/0 +transport_path_delays -sdfretain +neg_tchk -negdelay";
} else {
  $elab_opt = $elab_opt." +notimingcheck +nospecify"
}
print "sim_dir     = ".$simulator."\n";
print "vhdl_flag   = ".$vhdl_flag."\n";
print "os32bit     = ".$os32bit."\n";
print "comp_cmd    = ".$comp_cmd."\n";
print "elab_cmd    = ".$elab_cmd."\n";
print "sim_cmd     = ".$sim_cmd."\n";
print "seed        = ".$seed."\n";
print "cmp_dir    = ".$cmp_dir."\n";
print "sim_dir     = ".$sim_dir."\n";
print "lsf_enable  = ".$lsf_enable."\n";
print "comp_enable = ".$comp_enable."\n";
print "elab_enable = ".$elab_enable."\n";
print "sim_enable  = ".$sim_enable."\n";
print "comp_opt    = ".$comp_opt."\n";
print "elab_opt    = ".$elab_opt."\n";
print "sim_opt     = ".$sim_opt."\n";
print "comp_log_opt= ".$comp_log_opt."\n";
print "elab_log_opt= ".$elab_log_opt."\n";
print "sim_log_opt = ".$sim_log_opt."\n";
print "job_name    = ".$job_name."\n";

my $return_value;
my $my_cmd;
$my_cmd = $lsf_opt." ";
if(!-d $cmp_dir) {
  print "ERROR: Can't Find Compile Dir ($cmp_dir)!!!\n";
  exit(1);
}
if($comp_enable) {
  $my_cmd .= "cd $cmp_dir; ";
  $my_cmd .= $comp_cmd." -nc -error=noMPD ";
  $my_cmd .= $comp_log_opt." ";
  $my_cmd .= $comp_opt."; ";
 # $my_cmd .= "cd -; ";
}

if($elab_enable) {
  $my_cmd .= "cd $cmp_dir; ";
  $my_cmd .= $elab_cmd." ";
  $my_cmd .= $elab_log_opt." ";
  $my_cmd .= $elab_opt."; ";
 # $my_cmd .= "cd -; ";
}

if($sim_enable) {
  if(!-d $sim_dir) {
    print "ERROR: Can't Find Simulation Dir ($sim_dir)!!!";
    eixt(1);
  }
  $my_cmd .= "cd $sim_dir; ";
  $my_cmd .= $sim_cmd." ";
  $my_cmd .= $sim_log_opt." ";
  $my_cmd .= $sim_opt."; ";
 # $my_cmd .= "cd -; ";
}

if($comp_enable || $elab_enable || $sim_enable) {
  open SIM_LOG, ">$sim_dir/bsub_cmd.log";
  print $my_cmd."\n";
  if($lsf_enable) {
    if($lsf_post_script ne "") {
      $my_cmd .= " $lsf_post_script;";
    }
    $my_cmd .= "\"";
    print $my_cmd."\n";
    print SIM_LOG "$my_cmd\n";
    $return_value      = &get_bsub_id(`$my_cmd`);
  } else {
    $return_value      = system($my_cmd);
  }
  print STDOUT $return_value."\n";
  if($return_value != 0) {
    exit(1);
  }
} else {
  print "Error: There is no compile, elab or sim options enabled!!!\n";
  exit(1);
}

#--------------------------------------------------------------------------
# Perl Sub Modules
#--------------------------------------------------------------------------
sub get_bsub_id {
  my $bsub_return_value = shift @_;
  my $bsub_job_id = "no bsub";
  if($bsub_return_value =~ /<([0-9]+)>/) {
    $bsub_job_id = $1;
  }
  return $bsub_job_id;
}

